#include <iostream>
#include <string>
#include <map>

using namespace std;

//---------------------------------------------------------------------------------------------------------------------

class Employee
{

private:
	string EmpName;
	long SocialSecNum;

public:
        //Two overloaded constructor prototypes
	Employee();
	Employee(const string & name, const int SSN);

        //Copy constructor prototype
	Employee(const Employee & rhs);

        //Destructor prototype
	~Employee();

        //Accesor method prototypes - defined outside the class specification
	void	SetName(const string & name);
	string	GetName()	const;
	void	SetSSN(const int SSN);
	int	GetSSN()	const;

        //Overloaded assignment operator prototype
	Employee& operator=(const Employee& rhs);
};  

//Define two overloaded constructors
Employee::Employee():EmpName("New Employee"), SocialSecNum(666666666)
{ }

Employee::Employee(const string & name, const int SSN):EmpName(name), SocialSecNum(SSN)
{ }

//Define copy constructor
Employee::Employee(const Employee& rhs): EmpName(rhs.GetName()), SocialSecNum(rhs.GetSSN()){}

Employee::~Employee(){}

//Define accesor methods
void Employee::SetName(const string & name)
{
	EmpName = name;
}

string Employee::GetName() const
{
	return EmpName;
}

void Employee::SetSSN(const int SSN)
{
	SocialSecNum = SSN;
}

int Employee::GetSSN() const
{
	return SocialSecNum;
}

//Define overloaded assignment operator
Employee & Employee::operator=(const Employee & rhs)
{
	EmpName = rhs.GetName();
	SocialSecNum = rhs.GetSSN();
	return *this;
}

//---------------------------------------------------------------------------------------------------------------------

//Overload ostream operator to display the Name and SSN data member of an Employee object
ostream & operator<<(ostream & os, const Employee & rhs)
{
	os << rhs.GetName() << " has a social of " << rhs.GetSSN() << ".";
	return os;
}

//---------------------------------------------------------------------------------------------------------------------

template<class T, class A>

//Function prototype to display map properties
void ShowMap(const map<T, A> & v);

//---------------------------------------------------------------------------------------------------------------------

//Maps are a combination of a string identifier and the object it identifies
typedef map<string, Employee> TheCompany;

//---------------------------------------------------------------------------------------------------------------------

int main()
{
        //Create instances of Employee objects
	Employee GeorgeW("George W. Bush", 235648978);
	Employee JenniferLopez("Jennifer Lopez", 235984678);
	Employee MariahC("Mariah Carrey", 178963265);
	Employee DavidDuchovny("David Duchovny", 195693469);

        //Create a map container of Employee objects referenced by strings
	TheCompany SmallBusiness;

        //Store the Employee objects in the Map containers by their string key values
	SmallBusiness[GeorgeW.GetName()] = GeorgeW;
	SmallBusiness[JenniferLopez.GetName()] = JenniferLopez;
	SmallBusiness[MariahC.GetName()] = MariahC;
	SmallBusiness[DavidDuchovny.GetName()] = DavidDuchovny;

        cout << "Calling the ShowMap function.\n";
	cout << "SmallBusiness:\n";
	ShowMap(SmallBusiness);
      

        //Not expected - uses object name rather than string identifier, so will call Employee constructor for new object
 	cout << endl << endl << "Exited the function, now back in main()" << endl;


        //Not expected - uses object name rather than string identifier, so will call Employee constructor for new object
 	cout << endl << "Display using object name: " << endl;
        cout << "We know that " << SmallBusiness["MariahC"].GetName()
	     << " has a social of " << SmallBusiness["MariahC"].GetSSN() << ".\n";

         //What we want - uses string identifier rather than object name
        cout << endl << "Display using string identifier: " << endl;
        cout << "We know that " << SmallBusiness["Mariah Carrey"].GetName()
	     << " has a social of " << SmallBusiness["Mariah Carrey"].GetSSN() << ".\n";

	return 0;
} //close main()

//---------------------------------------------------------------------------------------------------------------------

template<class T, class A>
//Function definition.  Must use template declaration above.
void ShowMap(const map<T, A> & v)
{
     //Declare a const interator (like a pointer)
     map<T, A>::const_iterator ConstIter;

        //Use the overloaded ostream operator to display the data members of Employee objects.
	for(ConstIter = v.begin(); ConstIter != v.end(); ++ConstIter)
           
            //First display the key that references the object, then display the object via overloaded <<.
	    cout << ConstIter->first << ": " << ConstIter->second << "\n";

	cout << endl;
} 

